package net.jingkao.app.common;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import net.jingkao.app.bean.annotation.Broadcast;
import net.jingkao.app.bean.annotation.InjectIntentExtra;
import net.jingkao.app.bean.annotation.InjectLayout;
import net.jingkao.app.bean.annotation.InjectPreference;
import net.jingkao.app.bean.annotation.InjectResource;
import net.jingkao.app.bean.annotation.InjectView;
import net.jingkao.app.bean.annotation.InjectWebService;
import android.app.Activity;
import android.app.ListActivity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.preference.PreferenceActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.webkit.WebView;
import android.widget.Toast;

/**
 * UI工具包
 * @author chao
 *
 */
public class UIHelper {
	
	private static Logger log = Logger.getLog(UIHelper.class); 

	
	public static class ForbidWebViewLongClick implements WebView.OnLongClickListener{
        @Override
        public boolean onLongClick(View v) {
            return true;
        }
    }
	
	
	public static void injectResource(Activity activity){
		for( Field f: activity.getClass().getDeclaredFields()){
			InjectResource ir = f.getAnnotation(InjectResource.class);
			if(ir != null){
				try {
					f.setAccessible(true);
					f.set(activity, activity.getString(ir.value()));
				} catch (Exception e) {
					log.e(e, "Failed to inject resource to %s", f);
				}
			}
		}
	}
	
	public static void injectPreference(Activity activity){
		if(!(activity instanceof PreferenceActivity)){
			return ;
		}
		PreferenceActivity pa = (PreferenceActivity) activity;
		for( Field f: activity.getClass().getDeclaredFields()){
			InjectPreference ip = f.getAnnotation(InjectPreference.class);
			if(ip != null){
				try {
					f.setAccessible(true);
					f.set(pa, pa.findPreference(ip.value()));
					log.d("inject preference %s to %s", pa.findPreference(ip.value()), f);
				} catch (Exception e) {
					log.e(e, "Failed to inject preference to %s", f);
				}
			}
			
			
		}
	}
	
	public static void injectLayout(Activity activity){
		InjectLayout il = activity.getClass().getAnnotation(InjectLayout.class);
		if(il != null){
			if(il.content() > 0){
				if(activity instanceof PreferenceActivity){
					PreferenceActivity pa = (PreferenceActivity) activity;
					pa.addPreferencesFromResource(il.content());
				}else{
					activity.setContentView(il.content());
				}
			}
			
			if(activity instanceof ListActivity){
				ListActivity la = (ListActivity) activity;
				if(il.header() > 0){
					la.getListView().addHeaderView(LayoutInflater.from(activity).inflate(il.header(),  null));
				}
				if(il.footer() > 0){
					la.getListView().addFooterView(LayoutInflater.from(activity).inflate(il.footer(),  null));
				}
			}else{
				if(il.header() > 0){
					log.w("Failed to inject layout header because of %s does not instance of ListActivity", activity.getClass());
				}
				if(il.footer() > 0){
					log.w("Failed to inject layout footer because of %s does not instance of ListActivity", activity.getClass());
				}
			}
		}
	}
	
	public static void injectView(Activity activity){
		for( Field f: activity.getClass().getDeclaredFields()){
			InjectView ir = f.getAnnotation(InjectView.class);
			if(ir != null){
				try {
					f.setAccessible(true);
					View v = activity.findViewById(ir.value());
					if(v == null){
						log.w("Failed to inject view: %d => %s", ir.value(), f);
					}
					f.set(activity, v);
				} catch (Exception e) {
					log.e(e, "Failed to inject view to %s", f);
				}
			}
		}
	}
	
	
	public static void injectWebService(Activity activity){
		for( Field f: activity.getClass().getDeclaredFields()){
			InjectWebService iws = f.getAnnotation(InjectWebService.class);
			if(iws != null){
				try {
					f.setAccessible(true);
					f.set(activity, WebServices.proxy(f.getType()));
				} catch (Exception e) {
					log.e(e, "Failed to inject webservice to %s", f);
				}
			}
		}
	}
	
	public static void injectIntentExtra(Activity activity){
		for( Field f: activity.getClass().getDeclaredFields()){
			InjectIntentExtra iie = f.getAnnotation(InjectIntentExtra.class);
			if(iie != null){
				try {
					f.setAccessible(true);
					Class<?> type = f.getType();
					if(type.equals(String.class)){
						f.set(activity, activity.getIntent().getStringExtra(iie.value()));						
					}else if(type.equals(Integer.class) || type.getName().equals("int")){
						f.set(activity, activity.getIntent().getIntExtra(iie.value(), 0));
					}else if(type.equals(Long.class) || type.getName().equals("long")){
						f.set(activity, activity.getIntent().getLongExtra(iie.value(), 0));
					}else if(type.equals(Boolean.class) || type.getName().equals("boolean")){
						f.set(activity, activity.getIntent().getBooleanExtra(iie.value(), false));
					}else if (type.equals(Float.class) || type.getName().equals("float")) {
						f.set(activity, activity.getIntent().getFloatExtra(iie.value(), 0));
					} else if (type.equals(Double.class) || type.getName().equals("double")) {
						f.set(activity, activity.getIntent().getDoubleExtra(iie.value(), 0));
					}else{
						f.set(activity, activity.getIntent().getSerializableExtra(iie.value()));
					}
				} catch (Exception e) {
					log.e(e, "Failed to inject IntentExtra to %s", f);
				}
			}
		}
	}
	
	public static void injectAll(Activity activity){
		injectLayout(activity);
		injectResource(activity);
		injectView(activity);
		injectPreference(activity);
		injectWebService(activity);
		injectIntentExtra(activity);
	}
	
	public static void sendBroadcast(Activity activity,Intent intent){
		activity.sendBroadcast(intent); 
	}
	
	public static void sendBroadcast(Context context,Intent intent){
		context.sendBroadcast(intent); 
	}
	
	public static void processBoardcast(Activity activity, Intent intent){
		String action = intent.getAction();
		for(Method method : activity.getClass().getMethods()){
			Broadcast bc = method.getAnnotation(Broadcast.class);
			if(bc != null){
				if(bc.value().equals(action)){
					try {
						method.invoke(activity, intent);
					} catch (Exception e) {
						log.e(e, "Failed to invoke method[%s] with Boardcast[%s]", method, bc.value());
					}
				}
			}
		}
	}
	
	public static BroadcastRecieveProcessor registerBoardcast(Activity activity){
		IntentFilter myIntentFilter = new IntentFilter();
		BroadcastRecieveProcessor reciever = null;
		boolean hasReciever = false;
        //注册广播
		for(Method method : activity.getClass().getMethods()){
			Broadcast bc = method.getAnnotation(Broadcast.class);
			if(bc != null){
				myIntentFilter.addAction(bc.value());
				hasReciever = true;
			}
		}
		if(hasReciever){
			reciever = new BroadcastRecieveProcessor(activity);
			activity.registerReceiver(reciever, myIntentFilter);
		}
		return reciever;
	}
	
	public static String getAssetAsString(Context context, String fileName){
		InputStream in = null;
		try{
			in = context.getAssets().open(fileName);
			int i = -1;
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			while ((i = in.read()) != -1) {
			    baos.write(i);
			}
			String content = baos.toString();
			return content;
		}catch(Exception e){
			Logger.getLog(UIHelper.class).e(e);
			return "";
		}finally{
			if(in != null){
				try{
					in.close();
				}catch(Exception e){}
			}
		}
	}
	
	public static void showLongToast(Context context, String message){
		Toast.makeText(context, message, Toast.LENGTH_LONG).show();
	}
	
	public static void showShortToast(Context context, String message){
		Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
	}
	
	public static class BroadcastRecieveProcessor extends BroadcastReceiver{
		
		Activity activity;
		
		BroadcastRecieveProcessor(Activity activity){
			this.activity = activity;
		}

		@Override
		public void onReceive(Context context, Intent intent) {
			processBoardcast(activity, intent);
		}
		
	}
	
	
}
